import java.util.Stack;
import processing.core.*;
public class Sketch extends PApplet {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	int scale = 15; // must be >=2 to render correctly
	int mazeWidth = 10; // width in # of cells
	int mazeHeight = 10; // height in # of cells
	int spacing = 10; //size of border around maze in pixels
	int fps = 20; //fps to run animation at
	
	public Stack<Cell> stack = new Stack<Cell>(); //stack for DFS
	public Stack<Cell> Solvestack = new Stack<Cell>(); //stack for DFS
	public Maze maze = new Maze(mazeWidth, mazeHeight); //the maze

	Cell c; //to hold the active Cell
	Cell nextC; //to hold the upcoming cell

	@Override
	public void setup() {
		//size(spacing * 2 + scale * mazeWidth, spacing * 2 + scale * mazeHeight);
		//Cannot build processing applet with variables in the size() method, oh well
		size(180,180); //set size of the sketch
		frameRate(fps); //set fps
		ellipseMode(CORNER); //ellipses drawn using top-left corner as origin
		smooth(); //draw with anti-aliasing
		
		maze.getCell(mazeWidth - 1, mazeHeight - 1).setEnd(); // set bottom right Cell as END point
		maze.getCell(0,0).setStart(); //starting cell is the top-left cell
		c = maze.getCell(Rand.randomInt(mazeWidth),Rand.randomInt(mazeHeight)); //starting cell for algorithm is random!
		c.setVisited(); //mark it visited
		
		//go through the algorithm's process once so the stack isn't empty
		nextC = c.randomNeighbor(); //pick a random neighbor, nextC
		nextC.setVisited(); //mark it visited
		c.breakWall(nextC); //break the walls between c and nextC
		stack.push(c); //push c onto the stack
		c = nextC; //recurse with nextC as the new c
	}

	@Override
	public void draw() { //automatically loops at specified frameRate
		background(49,81,88); //black out background (clearing any drawing)
		maze.drawMaze(this); //draw the maze
		maze.markMaze(this); //mark start
		maze.markEnd(this); //mark end
		if (!stack.isEmpty()) {//if the maze is incomplete || account for stack starting empty
			if (c.isDeadEnd() || c.isEnd() || c.isStart()) { //if c has no unvisited neighbors, or it's the start/end cell, start backtracking...
				nextC = stack.pop();//by popping the last cell off the stack...
				c = nextC;//and recursing with it as c
			} else { // if there are unvisited neighbors...
				nextC = c.randomNeighbor(); //pick a random neighbor, nextC
				nextC.setVisited(); //mark it visited
				c.breakWall(nextC); //break the walls between c and nextC
				stack.push(c); //push c onto the stack
				c = nextC; //recurse with nextC as the new c
			}
			//c.ispath = true;
			stroke(204,0,0); //stroke black
			fill(204,0,0); //fill white
			ellipse(c.getX() * scale + spacing + 1, c.getY() * scale + spacing + 1, scale - 2, scale - 2); // draw 'stylus' ellipse
		}
		else if(!Solvestack.isEmpty()){
			Cell temp = c.pickNeighbor(this);
			if ( temp==null || c.isStart()||c.isEnd() || c.isEndtoPath() ||c.isDeadEnd() ) { //if c has no path to neighbors, start backtracking till there is path...
					if(c.isEnd()){//found goal
						noLoop(); //stop looping the draw() method
						//put green border to indicate completion
						int i = Solvestack.size();
						for(;i>0;i--){
							Cell c = Solvestack.pop();
							c.drawCellPath(this);
						}
						println("\nVisited a total of "+Maze.numSquaresVisited+" squares to solve");
						println("Maze is "+(mazeWidth*mazeHeight)+" squares big!");
						noFill();
						stroke(color(0,255,0));
						rect(0,0,width-1,height-1);
					}
					else{	
						nextC = Solvestack.pop();//by popping the last cell off the stack...
						c = nextC;//and recursing with it as c
					}
					
			} else{
				nextC = c.pickNeighbor(this); //pick a random visitable  neighbor, nextC
				if(nextC != null){
				nextC.setVisited(); //mark it visited
			
				Solvestack.push(c); //push c onto the stack
				c = nextC; //recurse with nextC as the new c
				c.setVisited();
				}
				else{
					nextC=Solvestack.pop();
				}
				
			}
		
			stroke(245,184,0); //stroke black
			fill(245,184,0); //fill white
			ellipse(c.getX() * scale + spacing + 1, c.getY() * scale + spacing + 1, scale - 4, scale - 4); // draw 'stylus' ellipse
			
		}

		else{ //maze is finished
			
			//maze.resetVisits();
			//nextC = maze.getCell(0,0); //start at beginning
			//nextC.setVisited(); //mark it visited
			//nextC.breakWall(nextC);
		//	Solvestack.push(c); //push c onto the stack
			//c = nextC; //recurse with nextC as the new c
			//println("The end!");
			//noLoop(); //stop looping the draw() method
			//put green border to indicate completion
			//noFill();
			//stroke(color(0,255,0));
			//rect(0,0,width-1,height-1);
		}
	}
	@Override
	public void mousePressed() {
		//maze.setMaze(); //set type of cells..
		//maze.printMaze();
		maze.resetVisits();
		maze.resetNumVisits();
		c = maze.getCell(0,0);
		c.setVisited(); //mark it visited
		nextC = c.pickNeighbor(this); //pick a random neighbor, nextC
		if(nextC != null){
			nextC.setVisited(); //mark it visited
			Solvestack.push(c); //push c onto the stack
			c = nextC; //recurse with nextC as the new c
		}
	}
	
	static public void main(String args[]) {
	     PApplet.main(new String[] { "Sketch" }  )  ;
	}
}
